﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;
using System.Xml;

namespace SharePoint.Orm.Caml {
	///<summary>
	/// The base of the CAML query. CamlQuery holds the where, orderby and groupby clause.
	///</summary>
	public class CamlQuery {
		public CamlWhere Where { get; set; }
		public CamlOrderBy OrderBy { get; set; }
		public CamlGroupBy GroupBy { get; set; }

		public void AppendWhere(CamlExpr expr) {
			if (Where == null) {
				Where = new CamlWhere();
			}
			Where.AppendWhere(expr);
		}

		public void AddOrderBy(CamlFieldRef fieldRef) {
			if (OrderBy == null) {
				OrderBy = new CamlOrderBy();
			}
			OrderBy.Fields.Add(fieldRef);
		}

		public XElement ToXml() {
			XElement queryElement = new XElement("Query");

			if (GroupBy != null && GroupBy.First != null) {
				queryElement.Add(GroupBy.ToXml());
			}

			if (OrderBy != null && OrderBy.Fields.Count > 0) {
				queryElement.Add(OrderBy.ToXml());
			}

			if (Where != null) {
				queryElement.Add(Where.ToXml());
			}

			return queryElement;
		}

		public override string ToString() {
			return ToString(true);
		}

		public string ToString(bool includeQueryElement) {
			XElement xml = ToXml();
			if (includeQueryElement) {
				return xml.ToString();
			}

			StringBuilder result = new StringBuilder();
			foreach (XNode node in xml.Nodes()) {
				result.AppendLine(node.ToString());
			}
			return result.ToString();
		}

		public static CamlQuery Parse(string str) {
			if (string.IsNullOrEmpty(str)) {
				str = "<Query/>";
			}
			str = str.Trim();
			if (!str.StartsWith("<Query")) {
				str = "<Query>" + str + "</Query>";
			}
			XElement elem = XElement.Parse(str);
			CamlQuery result = new CamlQuery();
			foreach (XElement child in elem.Elements()) {
				if (child.Name == "GroupBy") {
					result.GroupBy = CamlGroupBy.Parse(child);
				} else if (child.Name == "OrderBy") {
					result.OrderBy = CamlOrderBy.Parse(child);
				} else if (child.Name == "Where") {
					result.Where = CamlWhere.Parse(child);
				} else {
					throw new Exception("Unexpected element '" + child.Name + "'");
				}
			}
			return result;
		}
	}
}
